package cn.java.sy;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 二维码以及图片合成工具类
 *
 * @author dyca
 */
public class QRCodeUtils {

	public static BufferedImage enQRCode(String contents, int width, int height) throws WriterException {
		// 定义二维码参数
		final Map<EncodeHintType, Object> hints = new HashMap(8) {
			{
				// 编码
				put(EncodeHintType.CHARACTER_SET, "UTF-8");
				// 容错级别
				put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
				// 边距
				put(EncodeHintType.MARGIN, 0);
			}
		};
		return enQRCode(contents, width, height, hints);
	}

	/**
	 * 生成二维码
	 *
	 * @param contents
	 *            二维码内容
	 * @param width
	 *            图片宽度
	 * @param height
	 *            图片高度
	 * @param hints
	 *            二维码相关参数
	 * @return BufferedImage对象
	 * @throws WriterException
	 *             编码时出错
	 * @throws IOException
	 *             写入文件出错
	 */
	public static BufferedImage enQRCode(String contents, int width, int height, Map hints) throws WriterException {
		// String uuid = UUID.randomUUID().toString().replace("-", "");
		// 本地完整路径
		// String pathname = path + "/" + uuid + "." + format;
		// 生成二维码
		BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
		// Path file = new File(pathname).toPath();
		// 将二维码保存到路径下
		// MatrixToImageWriter.writeToPa(bitMatrix, format, file);
		// return pathname;
		return MatrixToImageWriter.toBufferedImage(bitMatrix);
	}

	/**
	 * 将图片绘制在背景图上
	 *
	 * @param backgroundPath
	 *            背景图路径
	 * @param zxingImage
	 *            图片
	 * @param x
	 *            图片在背景图上绘制的x轴起点
	 * @param y
	 *            图片在背景图上绘制的y轴起点
	 * @return
	 */
	public static BufferedImage drawImage(String backgroundPath, BufferedImage zxingImage, int x, int y)
			throws IOException {
		// 读取背景图的图片流
		BufferedImage backgroundImage;
		// Try-with-resources 资源自动关闭,会自动调用close()方法关闭资源,只限于实现Closeable或AutoCloseable接口的类
		try (InputStream imagein = new FileInputStream(backgroundPath)) {
			backgroundImage = ImageIO.read(imagein);
		}
		return drawImage(backgroundImage, zxingImage, x, y);
	}

	/**
	 * 将图片绘制在背景图上
	 *
	 * @param backgroundImage
	 *            背景图
	 * @param zxingImage
	 *            图片
	 * @param x
	 *            图片在背景图上绘制的x轴起点
	 * @param y
	 *            图片在背景图上绘制的y轴起点
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage drawImage(BufferedImage backgroundImage, BufferedImage zxingImage, int x, int y)
			throws IOException {
		Objects.requireNonNull(backgroundImage, ">>>>>背景图不可为空");
		Objects.requireNonNull(zxingImage, ">>>>>二维码不可为空");
		// 二维码宽度+x不可以超过背景图的宽度,长度同理
		if ((zxingImage.getWidth() + x) > backgroundImage.getWidth()
				|| (zxingImage.getHeight() + y) > backgroundImage.getHeight()) {
			throw new IOException(">>>>>二维码宽度+x不可以超过背景图的宽度,长度同理");
		}

		// 合并图片
		Graphics2D g = backgroundImage.createGraphics();
		g.drawImage(zxingImage, x, y, zxingImage.getWidth(), zxingImage.getHeight(), null);
		return backgroundImage;
	}

	/**
	 * 将文字绘制在背景图上
	 *
	 * @param backgroundImage
	 *            背景图
	 * @param x
	 *            文字在背景图上绘制的x轴起点
	 * @param y
	 *            文字在背景图上绘制的y轴起点
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage drawString(BufferedImage backgroundImage, String text, int x, int y, Font font,
			Color color) {
		// 绘制文字
		Graphics2D g = backgroundImage.createGraphics();
		
		
		
		// 设置颜色
		g.setColor(color);
		// 消除锯齿状
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
		// 设置字体
		g.setFont(font);
		// 绘制文字
		g.drawString(text, x, y);
		
		/*
		g.setFont(font);
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);//设置抗锯齿
	
		
		
		g.setPaint(new Color(0, 0, 0, 64));//阴影颜色
		g.drawString(text, x, y);//先绘制阴影
		g.setPaint(color);//正文颜色
		g.drawString(text, x, y);//用正文颜色覆盖上去
		*/
		
		
		return backgroundImage;
	}

	public static InputStream bufferedImageToInputStream(BufferedImage backgroundImage) throws IOException {
		return bufferedImageToInputStream(backgroundImage, "png");
	}

	/**
	 * backgroundImage 转换为输出流
	 *
	 * @param backgroundImage
	 * @param format
	 * @return
	 * @throws IOException
	 */
	public static InputStream bufferedImageToInputStream(BufferedImage backgroundImage, String format)
			throws IOException {
		ByteArrayOutputStream bs = new ByteArrayOutputStream();
		try (ImageOutputStream imOut = ImageIO.createImageOutputStream(bs)) {
			ImageIO.write(backgroundImage, format, imOut);
			InputStream is = new ByteArrayInputStream(bs.toByteArray());
			return is;
		}
	}

	/**
	 * 保存为文件
	 *
	 * @param is
	 * @param fileName
	 * @throws IOException
	 */
	public static void saveFile(InputStream is, String fileName) throws IOException {
		try (BufferedInputStream in = new BufferedInputStream(is);
				BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName))) {
			int len;
			byte[] b = new byte[1024];
			while ((len = in.read(b)) != -1) {
				out.write(b, 0, len);
			}
		}
	}

	// 二维码和溯源数字居中
	public static boolean sourceCodeImageGo(String backgroundImageFile, int backgroundImageWidth,
			int backgroundImageHeight, String qRContent, int qRCodeWidth, int qrCodeHeight, String sourceCode,
			int sourceCodeTextSize, String protectCode, int protectCodeTextSize, String outImageFile) {

		boolean b = false;

		// 二维码宽度
		int width = qRCodeWidth;
		// 二维码高度
		int height = qrCodeHeight;
		// 二维码内容
		String contcent = qRContent;
		BufferedImage zxingImage = null;
		try {
			// 二维码图片流
			zxingImage = QRCodeUtils.enQRCode(contcent, width, height);
		} catch (WriterException e) {
			e.printStackTrace();
			b = false;
			return b;
		}

		// 背景图片地址
		String backgroundPath = backgroundImageFile;

		InputStream inputStream = null;
		try {
			// 合成二维码和背景图
			// 二维码在居中
			int x = 0, y = 0;
			x = (int) ((backgroundImageWidth - qRCodeWidth) / 2);
			y = (int) ((backgroundImageHeight - qrCodeHeight) / 2);

			BufferedImage image = QRCodeUtils.drawImage(backgroundPath, zxingImage, x, y);

			// 绘制文字
			// Font font = new Font("微软雅黑", Font.BOLD, 10);
			Font font = new Font(null, Font.PLAIN, sourceCodeTextSize);
			String text = sourceCode;
			int tx = 0, ty = 0;
			tx = (backgroundImageWidth / 2)/*- (textSize * (sourceCode.length()/2))*/ ;
			// int bb = (textSize * sourceCode.length())/2;
			tx = tx - 40; // 40 是微调的

			ty = y + (qrCodeHeight);
			ty = ty + 8; // 8 是微调的

			image = QRCodeUtils.drawString(image, text, tx, ty, font, Color.BLACK);

			font = new Font(null, Font.PLAIN, protectCodeTextSize);
			text = protectCode;
			tx = (backgroundImageWidth / 2);
			tx = tx - 40; // 40 是微调的 16

			ty = y + (qrCodeHeight);
			ty = ty + 8; // 8 是微调的 16

			image = QRCodeUtils.drawString(image, text, tx, ty, font, Color.BLACK);

			// 图片转inputStream
			inputStream = QRCodeUtils.bufferedImageToInputStream(image);
		} catch (IOException e) {
			e.printStackTrace();
			b = false;
			return b;
		}
		// 保存的图片路径
		String originalFileName = outImageFile;
		try {
			// 保存为本地图片
			QRCodeUtils.saveFile(inputStream, originalFileName);
		} catch (IOException e) {
			e.printStackTrace();
			b = false;
		}

		b = true;
		return b;
	}

	public static boolean demoQRImage(String batchIdApplyId, String id, String codeSize, String codeStyle, String sourceCode,
			String protectCode) {

		boolean b = false;

		String appPath = FilePathUtil.getResourcePath();

		String backgroundImageFile = appPath + "static/qrbackimage/square200.png";

		int backgroundImageWidth = 200;
		int backgroundImageHeight = 200;

		if ("方形二维码".equals(codeStyle)) {
			backgroundImageFile = appPath + "static/qrbackimage/square200.png";
			backgroundImageWidth = 200;
			backgroundImageHeight = 200;
		} else if ("圆形带防码".equals(codeStyle)) {
			backgroundImageFile = appPath + "static/qrbackimage/square200.png";
			backgroundImageWidth = 200;
			backgroundImageHeight = 200;
		} else {
			backgroundImageFile = appPath + "static/qrbackimage/square200.png";
			backgroundImageWidth = 200;
			backgroundImageHeight = 200;
		}

		// String sourceCode = "5ac982540803123e"; // 16 位小写字母数字
		// String protectCode = "275738"; // 6 位防为码 数字

		String qRContent = Global.WEBAPI_QRURL + sourceCode;
		int qRCodeWidth = 90;
		int qrCodeHeight = 90;

		if ("45*45".equals(codeSize)) {
			qRCodeWidth = 45;
			qrCodeHeight = 45;
		} else if ("90*90".equals(codeSize)) {
			qRCodeWidth = 90;
			qrCodeHeight = 90;
		} else {
			qRCodeWidth = 90;
			qrCodeHeight = 90;
		}

		int sourceCodeTextSize = 8;
		int protectCodeTextSize = 8;

		String outImageFile = appPath + "static/sourcecodepackagepath/" + batchIdApplyId;

		File outImageFileObj = new File(outImageFile);

		if (!outImageFileObj.exists() && !outImageFileObj.isDirectory())
			outImageFileObj.mkdirs();

		String outImageFileName = outImageFile + "/" + id + ".png";

		b = sourceCodeImageGo(backgroundImageFile, backgroundImageWidth, backgroundImageHeight, qRContent, qRCodeWidth,
				qrCodeHeight, sourceCode, sourceCodeTextSize, protectCode, protectCodeTextSize, outImageFileName);

		return b;
	}

	public static void main(String[] args) {
		boolean b = false;
		String backgroundImageFile = "/Users/Administrator/Desktop/1.jpg";
		int backgroundImageWidth = 200;
		int backgroundImageHeight = 200;

		String sourceCode = "5ac982540803123e"; // 16 位小写字母数字
		String protectCode = "275738"; // 6 位防为码 数字

		String qRContent = "http://www.shine-tech.net/shtml/shine2018/index.shtml";
		// int qRCodeWidth = 45;
		// int qrCodeHeight = 45;

		int qRCodeWidth = 180;
		int qrCodeHeight = 180;

		int sourceCodeTextSize = 16;
		int protectCodeTextSize = 16;
		String outImageFile = "/Users/Administrator/Desktop/2.jpg";

		b = sourceCodeImageGo(backgroundImageFile, backgroundImageWidth, backgroundImageHeight, qRContent, qRCodeWidth,
				qrCodeHeight, sourceCode, sourceCodeTextSize, protectCode, protectCodeTextSize, outImageFile);

		System.out.println(b);

	}

	// public static void main(String[] args) {
	// //二维码宽度
	// int width = 90;
	// //二维码高度
	// int height = 90;
	// //二维码内容
	// String contcent =
	// "http://www.fagebaobao.com/sourcecode?q=fafjalkfjaklfakl";
	// BufferedImage zxingImage = null;
	// try {
	// //二维码图片流
	// zxingImage = CodeUtils.enQRCode(contcent, width, height);
	// } catch (WriterException e) {
	// e.printStackTrace();
	// }
	// //背景图片地址
	// String backgroundPath = "/Users/fagebaobao/Desktop/b.png";
	//
	// InputStream inputStream = null;
	// try {
	// //合成二维码和背景图
	// BufferedImage image = CodeUtils.drawImage(backgroundPath, zxingImage, 68,
	// 68);
	// //绘制文字
	// //Font font = new Font("微软雅黑", Font.BOLD, 10);
	//
	// Font font = new Font(null, Font.PLAIN, 8);
	//
	//
	// String text = "1234567890123456";
	//
	// image = CodeUtils.drawString(image, text, 30, 180,font,Color.BLACK);
	// //图片转inputStream
	// inputStream = CodeUtils.bufferedImageToInputStream(image);
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// //保存的图片路径
	// String originalFileName = "/Users/fagebaobao/Desktop/bd.png";
	// try {
	// //保存为本地图片
	// CodeUtils.saveFile(inputStream, originalFileName);
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// }
}
